/*
 * Copyright (c) 2012 Universidad Antonio de Nebrija.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0
 * which accompanies this distribution, and is available at
 * http://www.apache.org/licenses/LICENSE-2.0.html
 * 
 * Contributors:
 *    Universidad Antonio de Nebrija - initial API, implementation and documentation
 */
package com.nebrija.riif.parser;

import java.util.HashMap;

import org.antlr.runtime.tree.Tree;

import com.nebrija.riif.model.RIIFElement;

/**
 * Converts a tree into the RIIF model
 * @author asanchep
 *
 */
public class ASTRIIFConverter {

	/**
	 * Register with the processors in charge of convert a specific token
	 */
	protected HashMap<String,RIIFParserProcessor> processors 
			= new HashMap<String,RIIFParserProcessor>();
	
	//TODO: Turn it into a properties file with Reflection/Spring or similar.
	{
		// Mapping tokens to processors.
		processors.put("component",new ComponentElementProcessor());
		processors.put("fail_mode",new FailModeElementProcessor());
		processors.put("parameter",new ParameterElementProcessor());
		processors.put("constant",new ConstantElementProcessor());
		processors.put("assign",new AssignProcessor());
		processors.put("assert",new AssertProcessor());
		processors.put("child_component",new ChildComponentProcessor());
		processors.put("environment",new EnvironmentProcessor());
		processors.put("timeline",new TimelineProcessor());
		processors.put("state",new StateElementProcessor());
	}
	
	/**
	 * Function that converts a tree to the RIIF model
	 * @param t the tree to be converted
	 * @param base the element where it will be appended
	 * @return the base element 
	 */
	public RIIFElement processAST(Tree t, RIIFElement base){
		
		if (t==null){
			return base; 
		}
		
		// Apply the conversion
		RIIFElement newContainer = apply(base,t);
		// If no element is returned, assign the original container
		if (newContainer==null){ newContainer = base;}
		// Traverse the list of children
		for (int i=0;i<t.getChildCount();i++){
			if(t.getChild(i).getLine()==t.getLine()){
				continue;
			}
			// Recursive call to process the children
			newContainer= processAST(t.getChild(i),newContainer);
		}
		return base;
	}
	
	/**
	 * Convert a token to the associated object from the model using a processor
	 * @param container where the object resides
	 * @param t the tree with the information to be converted
	 * @return the new element or null if the conversion was not possible
	 */
	public RIIFElement apply(RIIFElement container, Tree t){
		String text = t.getText();
		if(text==null){
			return null;
		}
		RIIFParserProcessor proc = processors.get(text);
		if(proc==null){
			return null;
		}
		return proc.apply(container, t);
		
	}
}
